// @Time：2022/1/19 9:32
// @Software：GoLand
// @Author：JentZhang
package utils

import (
	"errors"
	"time"

	"github.com/dgrijalva/jwt-go"
)

// MyClaims 自定义声明结构体并内嵌jwt.StandardClaims
// jwt包自带的jwt.StandardClaims只包含了官方字段
// 我们这里需要额外记录一个username字段，所以要自定义结构体
// 如果想要保存更多信息，都可以添加到这个结构体中
type UserClaims struct {
	Username string `json:"username"`
	jwt.StandardClaims
}

type TokenInfo struct {
	Token  string `json:"token"`
	Expire string `json:"expire"`
}

const TokenExpireDuration = time.Hour * 12

var SECRET = []byte("雄关莫道真如铁，而今迈步从头越！")

// GenToken 生成token
func GenToken(username string) (t *TokenInfo, err error) {
	c := UserClaims{
		username,
		jwt.StandardClaims{
			ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), // 过期时间
			Issuer:    "gin_jwt_demo",                             // 签发人
		},
	}
	// fmt.Printf("claims:%#v", c)
	// 使用指定的签名方法创建签名对象
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
	// 使用指定的secret签名并获得完整的编码后的字符串token
	// fmt.Println(token.SignedString(SECRET))
	tokenStr := ""
	tokenStr, err = token.SignedString(SECRET)

	return &TokenInfo{
		Token:  tokenStr,
		Expire: time.Unix(c.ExpiresAt, 0).Format("2006-01-02 15:04:05"),
	}, err
}

// ParseToken 解析JWT
func ParseToken(tokenString string) (*UserClaims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &UserClaims{}, func(token *jwt.Token) (interface{}, error) {
		return SECRET, nil
	})
	if err != nil {
		return nil, err
	}
	if claims, ok := token.Claims.(*UserClaims); ok && token.Valid { // 校验token
		return claims, nil
	}
	return nil, errors.New("invalid token")
}
